<html>
	<head>
		<title>Parser Unit Test</title>
		<style type="text/css">
			@import "../resources/dojo.css";
		</style>
		<script type="text/javascript"
			src="../dojo.js"
			djConfig="isDebug: true, parseOnLoad: true"></script>
		<script type="text/javascript">
			dojo.require("dojo.parser");
			dojo.require("doh.runner");

			dojo.declare("tests.parser.Class1", null, {
				constructor: function(args, node){ dojo.mixin(this, args); }, 
				preambleTestProp: 1,
				preamble: function(){
					this.preambleTestProp++;
				},
				intProp: 1,
				callCount: 0, // for connect testing
				callInc: function(){ this.callCount++; },
				callCount2: 0, // for assignment testing
				strProp1: "original1",
				strProp2: "original2",
				arrProp: [],
				boolProp1: false,
				boolProp2: true,
				boolProp3: false,
				boolProp4: true,
				dateProp1: dojo.date.stamp.fromISOString('2007-01-01'),
				dateProp2: dojo.date.stamp.fromISOString('2007-01-01'),
				dateProp3: dojo.date.stamp.fromISOString('2007-01-01'),
				funcProp: function(){},
				funcProp2: function(){},
				funcProp3: function(){},
				onclick: function(){ this.prototypeOnclick=true; }
				// FIXME: have to test dates!!
				// FIXME: need to test the args property!!
			});

			dojo.declare("tests.parser.Class2", null, {
				constructor: function(){
					this.fromMarkup = false;
				}, 
				fromMarkup: false,
				markupFactory: function(args, node, classCtor){
					var i = new tests.parser.Class2();
					i.fromMarkup = true;
					return i;
				}
			});


			dojo.declare("tests.parser.Class3", tests.parser.Class2, {
				fromMarkup: false,
				markupFactory: function(args, node, classCtor){
					var i = new classCtor();
					i.classCtor = classCtor;
					return i;
				}
			});
			
			dojo.declare("tests.parser.inputClass", null, {
				constructor: function(args, node){ dojo.mixin(this, args); },
				// these attributes are special in HTML, they don't have a value specified
				disabled: false,
				checked: false
			});

			deepTestProp = {
				blah: {
					thinger: 1
				}
			};

			dojo.addOnLoad(function(){
				doh.register("t",
					[
						function testJsId(t){
							// console.debug(obj);
							t.t(typeof obj == "object");
						},

						// Attribute parsing tests
						function testStrProp(t){
							// normal string parameter
							t.t(dojo.isString(obj.strProp1));
							t.is("text", obj.strProp1);
							
							// make sure that you override a string value like "foo" to a blank value
							t.t(dojo.isString(obj.strProp2));
							t.is("", obj.strProp2);
						},
						function testIntProp(t){
							t.is("number", (typeof obj.intProp));
							t.is(5, obj.intProp);
						},
						function testArrProp(t){
							t.is(3, obj.arrProp.length);
							t.is(3, obj.arrProp[1].length);
							t.is(["foo", "bar", "baz"], obj.arrProp);
						},
						function testBoolProp(t){
							// make sure that both true and false get read correctly,
							// and that unspecified attributes' values don't change
							
							// boolProp1 specified at true
							t.is("boolean", (typeof obj.boolProp1));
							t.t(obj.boolProp1);
							
							// boolProp2 specified as false
							t.is("boolean", (typeof obj.boolProp2));
							t.f(obj.boolProp2);
							
							// boolProp3 not specified (prototype says false)
							t.is("boolean", (typeof obj.boolProp3));
							t.f(obj.boolProp3);
							
							// boolProp4 not specified (prototype says true)
							t.is("boolean", (typeof obj.boolProp4));
							t.t(obj.boolProp4);
						},
						function testDateProp(t){
							// dateProp1 specified as 2006-1-1
							t.is("2006-01-01", dojo.date.stamp.toISOString(obj.dateProp1, {selector: 'date'}));
							
							// dateProp2="", should map to NaN (a blank value on DateTextBox)
							t.t(isNaN(obj.dateProp2));
							
							// dateProp3="now", should map to current date
							t.is(dojo.date.stamp.toISOString(new Date(), {selector: 'date'}),
								dojo.date.stamp.toISOString(obj.dateProp3, {selector: 'date'}));
						},
						function testDisabledFlag(t){
							t.is("boolean", (typeof disabledObj.disabled));
							t.t(disabledObj.disabled);
							t.f(disabledObj.checked);
						},
						function testCheckedFlag(t){
							t.is("boolean", (typeof checkedObj.checked));
							t.f(checkedObj.disabled);
							t.t(checkedObj.checked);
						},
						function testFunctionProp(t){
							// make sure that unspecified functions (even with common names)
							// don't get overridden (bug #3074)
							obj.onclick();
							t.t(obj.prototypeOnclick);
							
							// funcProp2="foo"
							obj.funcProp2();
							t.t(obj.fooCalled);
							
							// funcProp3="this.func3Called=true;"
							obj.funcProp3();
							t.t(obj.func3Called);
						},

						// test <script> tags inside innerHTML of source node
						"t.is(4, obj.preambleTestProp);",
						"t.is(deepTestProp, obj.deepProp);",
						function testConnect(t){
							obj.callInc();
							t.is(2, obj.callCount);
						},
						function testFunctionAssignment(t){
							obj.callInc2();
							t.is(1, obj.callCount2);
						},
						function testSubNodeParse(t){
							t.f(dojo.exists("obj2"));
							var toParse = dojo.byId("toParse");
							toParse.setAttribute("dojoType", toParse.getAttribute("type"));
							dojo.parser.parse(toParse.parentNode);
							t.t(dojo.exists("obj2"));
							t.is("tests.parser.Class1", obj2.declaredClass);
						},
						function testMarkupFactory(t){
							t.t(dojo.exists("obj3"));
							t.t(obj3.fromMarkup);
						},
						function testMarkupFactoryClass(t){
							t.t(dojo.exists("obj4"));
							t.is(obj4.classCtor, tests.parser.Class3);
							t.t(obj4 instanceof tests.parser.Class3);
							t.t(obj4 instanceof tests.parser.Class2);
						},
						function testDisabledFlag(t){
							t.t(disabledObj.disabled);
							t.f(disabledObj.checked);
						},
						function testCheckedFlag(t){
							t.f(checkedObj.disabled);
							t.t(checkedObj.checked);
						}						
					]
				);
				doh.run();
			})
		</script>
	</head>
	<body>
		<h1>Parser Unit Test</h1>
		<script>
			function foo(){ this.fooCalled=true; }
		</script>
		<div dojoType="tests.parser.Class1" jsId="obj" 
			strProp1="text" strProp2=""
			intProp="5"
			arrProp="foo, bar, baz"
			boolProp1="true" boolProp2="false"
			dateProp1="2006-01-01" dateProp2="" dateProp3="now"
			funcProp2="foo" funcProp3="this.func3Called=true;"
		>
			<script type="dojo/method" event="preamble">
				this.preambleTestProp = 3;
			</script>
			<script type="dojo/method">
				// this should be run immediately
				this.deepProp = deepTestProp;
			</script>
			<script type="dojo/connect" event="callInc">
				this.callCount++;
			</script>
			<script type="dojo/method" event="callInc2">
				this.callCount2++;
			</script>
		</div>
		<div>
			<div type="tests.parser.Class1" jsId="obj2" id="toParse">
			</div>
		</div>
		<div dojoType="tests.parser.Class2" jsId="obj3">
		</div>
		<div dojoType="tests.parser.Class3" jsId="obj4">
		</div>
		<input dojoType="tests.parser.inputClass" jsId="checkedObj" checked type="checkbox">
		<button dojoType="tests.parser.inputClass" jsId="disabledObj" disabled>hi</button>
	</body>
</html>
